package sentinel.nacos.demo.config;

import java.util.Arrays;
import java.util.List;
import java.util.Properties;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect;
import com.alibaba.csp.sentinel.datasource.nacos.NacosDataSource;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.alibaba.nacos.api.PropertyKeyConst;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * @author Rocket
 */
@Configuration
public class SentinelConfiguration {

    /**
     * 配置sentinel aop支持
     * 例如 热点数据 @SentinelResource
     * @return
     */
    @Bean
    public SentinelResourceAspect sentinelResourceAspect() {
        return new SentinelResourceAspect();
    }

    @Bean
    public NacosDataSource nacosDataSource(ObjectMapper objectMapper) {
        // 1. nacos配置
        String serverAddress = "127.0.0.1:8848";
        //   nacos命名空间
        String namespace = "";
        // nacos 配置集编号
        // 推荐配置集编号的命名规则为 ${applicationName}-${ruleType}，
        // 例如我们这里是 demo-application-flow-rule，即 demo-application 应用的流控规则。
        String dataId = "demo-application-flow-rule";
        // 配置分组
        String group = "DEFAULT_GROUP";

        //  2. 创建nacosDataSource对象
        Properties properties = new Properties();
        properties.setProperty(PropertyKeyConst.SERVER_ADDR, serverAddress);
        properties.setProperty(PropertyKeyConst.NAMESPACE, namespace);

        NacosDataSource<List<FlowRule>> nacosDataSource = new NacosDataSource<>(properties, group, dataId,
            // <X> 转换器，将读取的 Nacos 配置，转换成 FlowRule 数组
            value -> {
                try {
                    return Arrays.asList(objectMapper.readValue(value, FlowRule[].class));
                } catch (JsonProcessingException e) {
                    throw new RuntimeException(e);
                }
            });

        // 注册到FlowManager中
        FlowRuleManager.register2Property(nacosDataSource.getProperty());
        return nacosDataSource;

        /**
         * nacos 配置集（限流）
         * 
         * [{
         *      // 资源名 即限流规则的作用对象
         *     "resource": "GET:/demo/echo",
         *     // 流控针对的调用来源，若为 default 则不区分调用来源
         *     "limitApp": "default",
         *     // 限流阈值类型（QPS 或并发线程数）
         *     "grade": 1,
         *     // 限流阈值
         *     "count": 5,
         *     // 调用关系限流策略
         *     "strategy": 0,
         *     // 流量控制效果（直接拒绝、Warm Up、匀速排队）
         *     "controlBehavior": 0,
         *     "clusterMode": false
         * }]
         */
    }
}
